package com.yst.webplugin.fieldhandler;

import com.yst.executor.Page;
import com.yst.spring.context.SpringContext;
import com.yst.web.utils.ClassUtils;
import com.yst.webplugin.additional.ResultProcessor;
import com.yst.webplugin.additional.mask.MaskConfigUtil;
import com.yst.webplugin.additional.transform.TransformConfigUtil;
import com.yst.webplugin.annotation.HttpInfo;
import com.yst.webplugin.annotation.Query;
import com.yst.webplugin.util.ParamUtils;
import lombok.SneakyThrows;
import org.sagacity.sqltoy.dao.SqlToyLazyDao;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class QueryHandler implements IFieldHandler {
    @Override
    public boolean accept(Field field) {
        return Objects.nonNull(field.getAnnotation(Query.class));
    }

    public static Object handleQuery(Field field,HttpInfo httpInfo,Map<String,Object> params) throws Exception {
        Query query=field.getAnnotation(Query.class);
        String sqlOrName= query.sqlOrSqlName();
        sqlOrName= sqlOrName.isEmpty() ? query.name() : sqlOrName;
        sqlOrName= sqlOrName.isEmpty() ? field.getName(): sqlOrName;
        SqlToyLazyDao sqlToyLazyDao= SpringContext.getContext().getBean(SqlToyLazyDao.class);

        if (ClassUtils.isAssignableFrom(field.getType(), Page.PageOut.class)){
            Page.PageIn pageIn=httpInfo.getBodyAs(Page.PageIn.class);
            ParamUtils.checkParams(params,query.validClass(),query.validClassGroup());

            org.sagacity.sqltoy.model.Page pageData= sqlToyLazyDao.findPageBySql(new org.sagacity.sqltoy.model.Page(pageIn.getPageSize(),pageIn.getPageIndex()),
                    sqlOrName, params ,query.modelClass());
            Page pageOut=new Page.PageOut(pageData.getRecordCount(),pageData.getRows()).setPageIndex(
                    pageData.getPageNo()).setPageSize(pageIn.getPageSize());

            ResultProcessor resultProcessor=new ResultProcessor()
                    .addAllFieldMaskConfig(MaskConfigUtil.fromField(field))
                    .addAllTransformConfig(TransformConfigUtil.fromField(field))
                    .addAllTransformConfig(TransformConfigUtil.fromClass(query.modelClass()))
                    .disableField(query.disabledFields());

            resultProcessor.deepProcess(pageOut,query.modelClass());
            return pageOut;
        }

        if (ClassUtils.isAssignableFrom(field.getType(), List.class)){

            ParamUtils.checkParams(params,query.validClass(),query.validClassGroup());

            List<?> data=sqlToyLazyDao.findBySql(sqlOrName,params,query.modelClass());
            ResultProcessor resultProcessor=new ResultProcessor()
                    .addAllFieldMaskConfig(MaskConfigUtil.fromField(field))
                    .addAllTransformConfig(TransformConfigUtil.fromField(field))
                    .addAllTransformConfig(TransformConfigUtil.fromClass(query.modelClass()))
                    .disableField(query.disabledFields());

            resultProcessor.deepProcess(data,query.modelClass());
            return data;
        }

        throw new RuntimeException(String.format("not supports type of the result:%s",
                field.getType().getName()));
    }

    @SneakyThrows
    @Override
    public void handle(Field field, HttpInfo httpInfo) {
        HashMap<String,Object> params=(HashMap<String, Object>) httpInfo.getBodyAs(HashMap.class);
        httpInfo.writeResult(handleQuery(field,httpInfo,params));
    }
}
